將多個物件連成一條鏈,沿著這條鏈傳遞至每一個物件並處理請求。
舉一個責任鏈模式在現實生活中的例子,就是公司員工請假。一般來說,一間公司核准請假天數的權限會因為職階不同而有所差異。比方說團隊主管核准的上限是7天、部門主管10天、技術總監15天之類的。當一個員工要請假10天,團隊主管無法核准這個假別,就會再往下一層提交,這就是責任鏈模式。
責任鏈模式中有兩個行為,一個是承擔責任,另一個則是把責任往下推。
一個純的責任鏈模式要求一個具體的處理者對象只能在兩個行為中選擇一個:一是承擔責任,另一個則是把責任推給下家。不允許出現某一個具體處理者對象在承擔了一部分責任後又 把責任向下傳的情況。
一個不純的責任鏈模式裡面,是允許只承擔部分責任,將其餘的責任往下推的情況,而且一個請求可以最終不被任何接收端對象所接收。
純的責任鏈模式的實際例子很難找到,一般看到的例子均是不純的責任鏈模式的實現。
成員 | 功用 |
---|---|
Handler | 定義一個處理請求的接口,包含抽象處理方法及後續方法。 |
ConcreteHandler | 實作Handler的處理方法,判斷是否可以處理這次的請求,可以則處理,不行則往後傳。 |
責任鏈結構圖
責任鏈
經由上圖可以發現,責任鏈就是處理任務或是將任務一段一段的往下傳。就如同一開始提到員工想請假,單位主管權限若不足,則將這個責任往部門主管傳下去。
了解完責任鏈的定義及架構後,現在來實作責任鏈模式。
首先就是建立抽象類別Handler,在內部定義好處理請求的方法其其餘的功能。
//抽象處理者:大領導類
abstract class Leader {
private Leader next;
private String name;
public Leader(String name){
this.name = name;
}
public void setNext(Leader next) {
this.next = next;
}
public Leader getNext() {
return next;
}
public void leaveSuccessed(int LeaveDays){
System.out.println(this.name + " approve your " + LeaveDays + " days leave.");
}
public void leaveFailed(){
System.out.println("There are too many days of leave, no one approved the leave slip!");
}
// 處理請求的方法
public abstract void handleRequest(int LeaveDays);
}
接著ConcreteHandler實作Handler,並在剛剛定義的方法內實作邏輯,每個主管級的權限不同,所以個邏輯也不同。
//實體處理者1:團隊經理
class TeamManager extends Leader {
public TeamManager(){
super("TeamManager");
}
public void handleRequest(int LeaveDays) {
if(LeaveDays <= 7) {
this.leaveSuccessed(LeaveDays);
}
else {
if (getNext() != null) {
getNext().handleRequest(LeaveDays);
}
else {
this.leaveFailed();
}
}
}
}
//實體處理者2:部門經理
class DepartmentManager extends Leader {
public DepartmentManager(){
super("DepartmentManager");
}
public void handleRequest(int LeaveDays) {
if(LeaveDays <= 10) {
this.leaveSuccessed(LeaveDays);
}
else {
if(getNext() != null) {
getNext().handleRequest(LeaveDays);
}
else {
this.leaveFailed();
}
}
}
}
//實體處理者3:院长类
class TechnicalDirector extends Leader {
public TechnicalDirector(){
super("TechnicalDirector");
}
public void handleRequest(int LeaveDays) {
if(LeaveDays <= 15) {
this.leaveSuccessed(LeaveDays);
}
else {
if(getNext() != null) {
getNext().handleRequest(LeaveDays);
}
else {
this.leaveFailed();
}
}
}
}
//實體處理者4:技術長
class CTO extends Leader{
public CTO(){
super("CTO");
}
public void handleRequest(int LeaveDays) {
if(LeaveDays <= 20) {
this.leaveSuccessed(LeaveDays);
}
else {
if(getNext()!=null) {
getNext().handleRequest(LeaveDays);
}
else {
this.leaveFailed();
}
}
}
}
最後在Client端就是把責任鏈組裝起來,比方說員工要請假,會先經由團隊經理審核,但天數太長的話,團隊經理權限不夠,任務只好往部門經理傳下去,以此類推。
public class LeaveApproval {
public static void main(String[] args) {
//組裝責任練
Leader teamManager = new TeamManager();
Leader departmentManager = new DepartmentManager();
Leader technicalDirector = new TechnicalDirector();
teamManager.setNext(departmentManager);
departmentManager.setNext(technicalDirector);
//提交請求
teamManager.handleRequest(8);
}
}
output
DepartmentManager approve your 8 days leave.
將多個物件連成一條鏈,沿著這條鏈傳遞至每一個物件並處理請求,當這個物件沒有處理的權限時,能夠將這個請求,傳遞給下一個物件繼續處理。
Handler:定義一個處理請求的接口,包含抽象處理方法及後續方法。
ConcreteHandler:實作Handler的處理方法,判斷是否可以處理這次的請求,可以則處理,不行則往後傳。
優點
1. 降低物件之間的耦合。
2. 增強系統的擴充性,可以根據需求增加新的處理類,滿足開閉原則。
3. 增強靈活性,可以動態的組成責任鏈。
4. 簡化物件之間的連接性。
5. 每個類別只處理自己該做的事,不處理就給別人做,符合單一職責原則。
缺點
1. 不能保證會被處理,可能到最後都沒有類別處理請求。
2. 較長的責任鏈可能會影響系統效能?
3. 增加Client的複雜性。
1. 動態的指定一組物件處理請求,或添加新的處理者。
2. 不確定由誰處理時,向多個處理者發送一個請求。
[https://www.jdoodle.com/a/2mKr](範例:Chain of Responsibility Pattern 實作)
责任链模式(职责链模式)详解
設計模式:責任鏈模式 (Chain-of-responsibility Pattern)